
// BloodleadDoc.cpp : implementation of the CBloodleadDoc class
//

#include "stdafx.h"
#include "Bloodlead.h"

#include "BloodleadDoc.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CBloodleadDoc

IMPLEMENT_DYNCREATE(CBloodleadDoc, CDocument)

BEGIN_MESSAGE_MAP(CBloodleadDoc, CDocument)
END_MESSAGE_MAP()


// CBloodleadDoc construction/destruction

CBloodleadDoc::CBloodleadDoc()
{
	// TODO: add one-time construction code here
	mInventTime = 0;
	mSamplingTime = 0;
	mIndex = 0;
	mProcessPause = FALSE;
}

CBloodleadDoc::~CBloodleadDoc()
{
}

// CBloodleadDoc diagnostics

#ifdef _DEBUG
void CBloodleadDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CBloodleadDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

void CBloodleadDoc::SaveSetting( DOUBLE fInventTime, DOUBLE fSamplingTime )
{
	mInventTime = fInventTime;
	mSamplingTime = fSamplingTime;
}

void CBloodleadDoc::AppendRecordset( DOUBLE fElcValueX, DOUBLE fElcValueY )
{
	Recordset rs;
	rs.mProcessed = FALSE;
	rs.mX = fElcValueX;
	rs.mY = fElcValueY;
	rs.mXY = fElcValueY*fElcValueX;
	rs.mXX = fElcValueX*fElcValueX;
	rs.mYY = fElcValueY*fElcValueY;

	mRecordsetArray.Add( rs );
}

void CBloodleadDoc::SetRecordset( INT_PTR nIndex, DOUBLE fValueX, DOUBLE fValueY )
{
	Recordset& rs = mRecordsetArray.GetAt( nIndex );
	rs.mX = fValueX;
	rs.mY = fValueY;
	rs.mXY = fValueY*fValueX;
	rs.mXX = fValueX*fValueX;
	rs.mYY = fValueY*fValueY;
}

void CBloodleadDoc::ClearAll()
{
	mRecordsetArray.RemoveAll();
	mIndex = 0;
}

UINT CBloodleadDoc::ElcCount()
{
	return mElcArray.GetCount();
}

UINT CBloodleadDoc::ElcValue( INT_PTR nIndex )
{
	return mElcArray.GetAt( nIndex );
}

BOOL CBloodleadDoc::GetRecordFlag( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mProcessed;
}

VOID CBloodleadDoc::SetRecordFlag( INT_PTR nIndex, BOOL bFlag )
{
	ASSERT( nIndex < mRecordsetArray.GetCount() );

	Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	ElcValue.mProcessed = bFlag;
}

DOUBLE CBloodleadDoc::GetElcValueX( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mX;
}

DOUBLE CBloodleadDoc::GetElcValueY( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mY;
}

DOUBLE CBloodleadDoc::GetElcValueXX( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mXX;
}

DOUBLE CBloodleadDoc::GetElcValueXY( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mXY;
}

DOUBLE CBloodleadDoc::GetElcValueYY( INT_PTR nIndex )const
{
	if( nIndex >= mRecordsetArray.GetCount() )
		return 0;

	CONST Recordset& ElcValue = mRecordsetArray.GetAt( nIndex );
	return ElcValue.mYY;
}

DOUBLE CBloodleadDoc::CalculateR()
{
	mX_AVG = 0.0f;
	mY_AVG = 0.0f;

	mXY_AVG = 0.0f;
	
	mXY_SUM = mXX_SUM = mYY_SUM = 0.0f;

	for( INT_PTR nIndex = 0; nIndex < mRecordsetArray.GetCount(); ++nIndex )
	{
		Recordset& v = mRecordsetArray.GetAt( nIndex );
		mX_AVG += v.mX;
		mY_AVG += v.mY;

		mXY_SUM += v.mXY;
		mXX_SUM += v.mXX;
		mYY_SUM += v.mYY;
	}

	UINT nCount = mRecordsetArray.GetCount();
	mX_AVG /= nCount;
	mY_AVG /= nCount;
	mXY_AVG = mX_AVG*mY_AVG;

	mL_xy = mXY_SUM - nCount*mXY_AVG;
	mL_xx = mXX_SUM - nCount*mX_AVG*mX_AVG;
	mL_yy = mYY_SUM - nCount*mY_AVG*mY_AVG;

	mB1 = mL_xy/mL_xx;
	mB0 = mY_AVG - mB1 * mX_AVG;

	return mL_xy/(sqrt(mL_xx)*sqrt(mL_yy));
}

VOID CBloodleadDoc::CalculateY( INT_PTR nIndex, DOUBLE fValueX )
{
	SetRecordset( nIndex, fValueX, mB1 * fValueX + mB0 );
}

void CBloodleadDoc::AppendElcValue( UINT nElcValue )
{
	mElcArray.Add( nElcValue );
}

DOUBLE CBloodleadDoc::CalculateX( INT_PTR nBegin, INT_PTR nEnd )
{
	nBegin = max( 0, nBegin );
	nEnd = min( nEnd, mElcArray.GetCount() );

	if( nBegin == nEnd )
		return 0.0f;

	UINT nSum = 0;
	for( INT_PTR nIndex = nBegin; nIndex < nEnd; ++nIndex )
	{
		nSum += mElcArray[nIndex] * 2;
	}

	nSum -= mElcArray[nBegin] + mElcArray[nEnd-1];

	return nSum * mInventTime * 0.5f;
}

// CBloodleadDoc commands
